package string;

import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class StringUtil {

    /**
     * 判断数组的整数是否连续,且相同的数字只能出现1次，最小值必须从1开始
     * @param list
     * @return
     */
    public static Boolean isSeries2(List<Integer> list){
        if(list==null || list.size()==0){
            return false;
        }

        Integer maxValue = Collections.max(list);
        Integer minValue = Collections.min(list);

        if(minValue.equals(1) && maxValue-minValue == list.size()-1){

            return true;

        }else {

            return false;
        }
    }
    public static Boolean isSeries(List<Integer> list){
        if(list==null || list.size()==0){
            return false;
        }
        int[] temp = new int[list.size()];
        Arrays.fill(temp,0);
        try{
            for (int i = 0; i < list.size(); i++) {
                int j = list.get(i);
                temp[j-1] = j;
            }
        }catch (ArrayIndexOutOfBoundsException e){
            return false;
        }
        for (int i = 0; i < temp.length; i++) {
            if(temp[i] == 0){
                return false;
            }
        }

        return true;
    }

    /**
     * 通过boolean类型的数组实现，这并不是最优秀的方法，
     * 摘自网络：
     * 4个字节
     * 理由来源是《Java虚拟机规范》一书中的描述：“虽然定义了boolean这种数据类型，但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令，
     * Java语言表达式所操作的boolean值，在编译之后都使用Java虚拟机中的int数据类型来代替，而boolean数组将会被编码成Java虚拟机的byte数组，每个元素boolean元素占8位”。
     * 这样我们可以得出boolean类型占了单独使用是4个字节，在数组中又是1个字节。
     * 显然第三条是更准确的说法，那虚拟机为什么要用int来代替boolean呢？为什么不用byte或short，这样不是更节省内存空间吗。大多数人都会很自然的这样去想，
     * 我同样也有这个疑问，经过查阅资料发现，使用int的原因是，对于当下32位的处理器（CPU）来说，一次处理数据是32位（这里不是指的是32/64位系统，而是指CPU硬件层面），
     * 具有高效存取的特点。
     * 所以本质上跟用byte[]是一样的
     * @param list
     * @return
     */
    public static Boolean isSeries3(List<Integer> list){
        if(list==null || list.size()==0){
            return false;
        }
        byte[] temp = new byte[list.size()];
        Arrays.fill(temp,(byte)0);
        try{
            for (int i = 0; i < list.size(); i++) {
                int j = list.get(i);
                temp[j-1] = (byte)1;
            }
        }catch (ArrayIndexOutOfBoundsException e){
            return false;
        }
        for (int i = 0; i < temp.length; i++) {
            if(temp[i] == (byte)0){
                return false;
            }
        }

        return true;
    }

    /**
     * 通过bitset实现，
     * 发现并不能实现，原有是BitSet底层是一个long[]数组，一个Long是64位，所以长度会是64的整数倍，并不是
     * 用户输入的个数
     * @param list
     * @return false，无法返回实际结果
     */
    public static Boolean isSeries4(List<Integer> list){
        if(list==null || list.size()==0){
            return false;
        }
        BitSet bitSet = new BitSet(list.size());
        try{
            for (int i = 0; i < list.size(); i++) {
                int j = list.get(i);
                bitSet.set(j,true);
            }
        }catch (ArrayIndexOutOfBoundsException e){
            return false;
        }
        for (int i = 1; i <= bitSet.size(); i++) {
            if(bitSet.get(i) == false){
                return false;
            }
        }

        return true;
    }

    public static Boolean isSeries5(List<Integer> list){
        if(list==null || list.size()==0){
            return false;
        }
        BitMap bitSet = new BitMap(list.size());
        try{
            for (int i = 0; i < list.size(); i++) {
                int j = list.get(i);
                bitSet.set(j);
            }
        }catch (ArrayIndexOutOfBoundsException e){
            return false;
        }
        for (int i = 1; i <= bitSet.size(); i++) {
            if(bitSet.get(i) == false){
                return false;
            }
        }

        return true;
    }

    public static void main(String[] args) {
        /*List<Integer> list = new ArrayList<>();
        Random random = new Random(System.currentTimeMillis());
        for (int i = 0; i < 100000000; i++) {
            list.add(random.nextInt());
        }

        long lnow = System.currentTimeMillis();
        boolean b = isSeries(list);
        System.out.println(System.currentTimeMillis() - lnow);
        lnow = System.currentTimeMillis();
        isSeries2(list);
        System.out.println(System.currentTimeMillis() - lnow);*/

        List<Integer> list = new ArrayList<>();
        /*list.add(Integer.valueOf(1));
        list.add(Integer.valueOf(2));
        list.add(Integer.valueOf(3));
//        list.add(Integer.valueOf(3));
        list.add(Integer.valueOf(4));
        list.add(Integer.valueOf(5));
        list.add(Integer.valueOf(6));
        list.add(Integer.valueOf(6));*/
        for (int i = 0; i < 330; i++) {
            list.add(i+1);
        }
//        System.out.println(isSeries3(list));
//        System.out.println(isSeries4(list));
        System.out.println(isSeries5(list));
    }

}
